import pandas as pd
import numpy as np
import logging
from datetime import datetime

class DataHandler:
    def __init__(self):
        self.df = None
        self.operation_history = []
        self.redo_history = []
    
    def load_excel(self, file_path):
        """加载Excel文件并验证格式"""
        try:
            file_ext = file_path.lower().split('.')[-1]
            if file_ext not in ['xlsx', 'xls']:
                raise ValueError('不支持的文件格式，请使用.xlsx或.xls格式的Excel文件')
            self.df = pd.read_excel(file_path)
            return self.df
        except Exception as e:
            logging.error(f'加载Excel文件失败: {str(e)}')
            raise
    
    def save_excel(self, file_path):
        """保存Excel文件"""
        try:
            self.df.to_excel(file_path, index=False)
            logging.info(f'文件已保存: {file_path}')
        except Exception as e:
            logging.error(f'保存Excel文件失败: {str(e)}')
            raise
    
    def get_statistics(self):
        """获取数据统计信息"""
        return {
            'row_count': len(self.df),
            'column_count': len(self.df.columns),
            'null_count': self.df.isnull().sum().sum()
        }
    
    def get_column_types(self):
        """获取列数据类型"""
        return self.df.dtypes
    
    def remove_spaces(self, columns):
        """删除指定列的空格"""
        for col in columns:
            if self.df[col].dtype == object:
                self.df[col] = self.df[col].str.strip()
        return self.df
    
    def normalize_case(self, case_type, columns):
        """统一大小写"""
        for col in columns:
            if self.df[col].dtype == object:
                if case_type == 'lower':
                    self.df[col] = self.df[col].str.lower()
                elif case_type == 'upper':
                    self.df[col] = self.df[col].str.upper()
                elif case_type == 'title':
                    self.df[col] = self.df[col].str.title()
        return self.df
    
    def format_numbers(self, decimal_places, columns):
        """格式化数字"""
        for col in columns:
            if pd.api.types.is_numeric_dtype(self.df[col]):
                self.df[col] = self.df[col].round(decimal_places)
        return self.df
    
    def format_dates(self, date_format, columns):
        """格式化日期"""
        for col in columns:
            if pd.api.types.is_datetime64_any_dtype(self.df[col]):
                self.df[col] = self.df[col].dt.strftime(date_format)
        return self.df
    
    def remove_special_chars(self, pattern, columns):
        """删除特殊字符"""
        for col in columns:
            if self.df[col].dtype == object:
                self.df[col] = self.df[col].str.replace(pattern, '', regex=True)
        return self.df
    
    def fill_empty_values(self, method, value=None, columns=None):
        """填充空值"""
        if columns is None:
            columns = self.df.columns
        for col in columns:
            if method == 'value':
                self.df[col].fillna(value, inplace=True)
            elif method == 'mean':
                if pd.api.types.is_numeric_dtype(self.df[col]):
                    self.df[col].fillna(self.df[col].mean(), inplace=True)
            elif method == 'median':
                if pd.api.types.is_numeric_dtype(self.df[col]):
                    self.df[col].fillna(self.df[col].median(), inplace=True)
            elif method == 'mode':
                self.df[col].fillna(self.df[col].mode()[0], inplace=True)
            elif method == 'ffill':
                self.df[col].fillna(method='ffill', inplace=True)
            elif method == 'bfill':
                self.df[col].fillna(method='bfill', inplace=True)
        return self.df

    def remove_empty_rows(self):
        """删除空行
        删除所有单元格都为空值（包括NaN、None、空字符串）的行
        """
        try:
            # 检查每个单元格是否为空（包括NaN、None和空字符串）
            is_empty = self.df.apply(lambda x: x.isna() | (x.astype(str).str.strip() == ''))
            # 找出所有单元格都为空的行
            empty_rows = is_empty.all(axis=1)
            # 删除空行
            self.df = self.df[~empty_rows]
            logging.info(f'已删除 {empty_rows.sum()} 个空行')
            return self.df
        except Exception as e:
            logging.error(f'删除空行失败: {str(e)}')
            raise